package eu.jakubiak.dto.copy;

import java.lang.reflect.InvocationTargetException;

import eu.jakubiak.dto.annotations.DataTransferObject;
import eu.jakubiak.dto.annotations.DtoHelper;
import eu.jakubiak.dto.manager.IDtoManager;
import eu.jakubiak.javabean.BeanProperty;


public class DtoCopyHelper implements IDtoCopyHelper {

	@SuppressWarnings("unchecked")
	public <T> void copy(IDtoManager manager, BeanProperty property, T from, T into) {
		try {
			T value = (T)property.getGetterMethod().invoke(from);
			if(value==null) {
				property.getSetterMethod().invoke(into, value);
			} else if(property.isAnnotationPresent(DtoHelper.class)) {
				DtoHelper helper = (DtoHelper) property.getAnnotation(DtoHelper.class);
				IDtoCopyHelper copyHelper = (IDtoCopyHelper)helper.value().newInstance();
				copyHelper.copy(manager, property, from, into);
			} else if(property.getType().isAnnotationPresent(DataTransferObject.class)) {
				T currentValue = (T)property.getGetterMethod().invoke(into);
				if(currentValue==null) {
					currentValue = (T)property.getType().newInstance();
					property.getSetterMethod().invoke(into, currentValue);					
				}
				currentValue = (T)manager.copy(property.getType(), value, currentValue);
				
			} else {
				property.getSetterMethod().invoke(into, value);
			}
		} catch (InstantiationException e) { 
			throw new RuntimeException(e);
		} catch (IllegalArgumentException e) {
			throw new RuntimeException(e);
		} catch (IllegalAccessException e) {
			throw new RuntimeException(e);
		} catch (InvocationTargetException e) {
			throw new RuntimeException(e);
		} catch( NullPointerException e) {
			throw e;
		}
	}
	
	
}
